package com.nbjtjc.safe.service.know;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nbjtjc.safe.bean.Page;
import com.nbjtjc.safe.bean.Result;
import com.nbjtjc.safe.mapper.danger.SafeDangerInspectLabelMapper;
import com.nbjtjc.safe.mapper.know.SafeKnowLabelMapper;
import com.nbjtjc.safe.mapper.know.SafeLabelMapper;
import com.nbjtjc.safe.model.danger.DangerInspectTableLabel;
import com.nbjtjc.safe.model.danger.SafeDangerInspectLabel;
import com.nbjtjc.safe.model.know.SafeKnowLabel;
import com.nbjtjc.safe.model.know.SafeLabel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.util.StringUtil;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SafeLabelService {
    @Autowired
    private SafeLabelMapper safeLabelMapper;
    @Autowired
    private SafeKnowLabelMapper safeKnowLabelMapper;
    @Autowired
    private SafeDangerInspectLabelMapper safeDangerInspectLabelMapper;

    @Autowired
    private SafeKnowledgeService safeKnowledgeService;

    public Result add(SafeLabel label) {
        Result result = new Result();
        if (ObjectUtil.isNull(label)) {
            result.setFalse("不能为空");
            return result;
        }
        SafeLabel temp = safeLabelMapper.selectOne(label);
        if (ObjectUtil.isNotNull(temp)) {
            result.setFalse("该标签已经存在");
            return result;
        }
        safeLabelMapper.insertSelective(label);
        result.setData(label);
        return result;
    }

    @Transactional(rollbackFor = {Throwable.class})
    public Result delete(List<String> safeLabels, int deleteLabelId) {
        Result result = new Result();
//        if (ObjectUtil.isNull(label)) {
//            result.setFalse("不能为空");
//            return result;
//        }
//        //TODO 删除重复问题
//        safeLabelMapper.deleteByLabel(label);
//        safeKnowLabelMapper.deleteByLabel(label);
        if (CollectionUtil.isEmpty(safeLabels)) {
            result.setFalse("不能为空");
            return result;
        }
        List<Integer> validKnowIds = safeKnowledgeService.searchValidKnowIds(safeLabels);
        String deleteLabel = safeLabels.get(safeLabels.size() - 1);
        if (CollectionUtil.isNotEmpty(validKnowIds)) {
            validKnowIds.forEach(knowId -> {
                safeKnowLabelMapper.deleteByLabelAndKnowId(deleteLabel, knowId);
            });
        }
        safeLabelMapper.deleteByPrimaryKey(deleteLabelId);
        return result;
    }

    @Transactional(rollbackFor = {Throwable.class})
    public Result update(SafeLabel safeLabel) {
        Result result = new Result();
        if (ObjectUtil.isNull(safeLabel) || ObjectUtil.isNull(safeLabel.getLabel())) {
            result.setFalse("不能为空");
            return result;
        }
        SafeLabel oldLabel = safeLabelMapper.selectByPrimaryKey(safeLabel.getId());
        if (ObjectUtil.isNull(oldLabel)) {
            result.setFalse("数据库中无此标签");
            return result;
        }
        safeLabelMapper.updateByPrimaryKeySelective(safeLabel);
        safeKnowLabelMapper.updateByLabel(oldLabel.getLabel(), safeLabel.getLabel());
        result.setData(safeLabel);
        return result;
    }

    public PageInfo findLabelStr(SafeLabel label, Page page){
        PageHelper.startPage(page.getPageCurrent(), page.getPageSize());
        List<String> labels=safeLabelMapper.findLabelStr(label.getCompanyId());

        return new PageInfo<>(labels);
    }

    public Result find(SafeLabel label, Page page) {
        Result result = new Result();
        if (ObjectUtil.isNull(label)) {
            result.setFalse("不能为空");
            return result;
        }
        PageHelper.startPage(page.getPageCurrent(), page.getPageSize());
        List<SafeLabel> safeLabels = safeLabelMapper.search(label);
        List<Integer> labelIds = safeLabels.stream().map(SafeLabel::getId).collect(Collectors.toList());
        label.setParentIds(labelIds);
        List<SafeLabel> labelSonCounts = safeLabelMapper.getSonCount(label);
        Map<Integer, SafeLabel> tempMap=new HashMap<>();
        if(CollectionUtil.isNotEmpty(safeLabels)){
            tempMap= safeLabels.stream().collect(Collectors.toMap(SafeLabel::getId, safeLabel -> safeLabel));
        }
        Map<Integer, SafeLabel> labelMap=tempMap;
        if (CollectionUtil.isNotEmpty(labelSonCounts)) {
            labelSonCounts.forEach(safeLabel -> {
                if (safeLabel.getSonCount() > 0) {
                    if(ObjectUtil.isNotNull(labelMap.get(safeLabel.getParent()))){
                        labelMap.get(safeLabel.getParent()).setHasSon(true);
                    }
                } else {
                    if(ObjectUtil.isNotNull(labelMap.get(safeLabel.getParent()))){
                        labelMap.get(safeLabel.getParent()).setHasSon(false);
                    }
                }
            });
        }
        result.setData(new PageInfo<>(safeLabels));
        return result;
    }

    /**
     * @param label        搜索的标签
     * @param searchLabels 被搜索到的知识点必须都包含这些标签
     * @return
     */
    public Result topLabel(String label, ArrayList<String> searchLabels) {
        Result result = new Result();
        if (ObjectUtil.isNull(label) || StringUtil.isEmpty(label)) {
            List<SafeKnowLabel> safeKnowLabels = safeKnowLabelMapper.topLabel(new ArrayList<>());
            result.setData(safeKnowLabels);
            return result;
        }
        HashSet<Integer> validateKnowIds = new HashSet<>();
        List<Integer> knowIds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(searchLabels) && searchLabels.size() >= 1) {
            knowIds = safeKnowLabelMapper.knowIdsByLabel(searchLabels.get(0));
            validateKnowIds.addAll(knowIds);
            for (int i = 1; i < searchLabels.size(); i++) {
                List<Integer> labelKnowIds = safeKnowLabelMapper.knowIdsByLabel(searchLabels.get(i));
                validateKnowIds.retainAll(labelKnowIds);
            }
        }
        if (CollectionUtil.isEmpty(validateKnowIds)) {
            result.setData(new ArrayList<>());
            return result;
        }
        List<SafeKnowLabel> safeKnowLabels = safeKnowLabelMapper.topLabel(new ArrayList<>(validateKnowIds));
        result.setData(safeKnowLabels);
        return result;
    }

    /**
     * 检查表的标签，
     *
     * @param label
     * @param searchLabels
     * @return
     */
    public Result inspectLabel(String label, ArrayList<String> searchLabels) {
        Result result = new Result();
        if (ObjectUtil.isNull(label) || StringUtil.isEmpty(label)) {
            List<SafeDangerInspectLabel> dangerInspectLabels = safeDangerInspectLabelMapper.topLabel(new ArrayList<>());
            result.setData(dangerInspectLabels);
            return result;
        }
        HashSet<Integer> validateKnowIds = new HashSet<>();
        List<Integer> knowIds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(searchLabels) && searchLabels.size() >= 1) {
            knowIds = safeDangerInspectLabelMapper.inspectIdsByLabel(searchLabels.get(0));
            validateKnowIds.addAll(knowIds);
            for (int i = 1; i < searchLabels.size(); i++) {
                List<Integer> labelKnowIds = safeDangerInspectLabelMapper.inspectIdsByLabel(searchLabels.get(i));
                validateKnowIds.retainAll(labelKnowIds);
            }
        }
        if (CollectionUtil.isEmpty(validateKnowIds)) {
            result.setData(new ArrayList<>());
            return result;
        }
        List<SafeDangerInspectLabel> safeDangerInspectLabels = safeDangerInspectLabelMapper.topLabel(new ArrayList<>(validateKnowIds));
        result.setData(safeDangerInspectLabels);
        return result;
    }

    public List<SafeLabel> getLabelStructure(int companyId) {
        SafeLabel safeLabel = new SafeLabel();
        safeLabel.setCompanyId(companyId);
        Map<Integer, List<SafeLabel>> parentIdLabelMap = new HashMap<>();
        List<SafeLabel> safeLabels = safeLabelMapper.select(safeLabel);
        safeLabels.forEach(label -> {
            if (!parentIdLabelMap.containsKey(label.getParent())) {
                List<SafeLabel> labels = new ArrayList<>();
                labels.add(label);
                parentIdLabelMap.put(label.getParent(), labels);
            } else {
                parentIdLabelMap.get(label.getParent()).add(label);
            }
        });
        List<SafeLabel> topLabels = new ArrayList<>();
        if (parentIdLabelMap.containsKey(0)) {
            topLabels = parentIdLabelMap.get(0);
            compareSubLabels(topLabels, parentIdLabelMap);
        }
        return topLabels;
    }

    /**
     * 获取标签的整个结构树
     *
     * @param labelString
     * @return
     */
    public Result constructLabel(Set<String> labelString, int companyId) {
        List<String> labelRouteRelations = labelString.stream().collect(Collectors.toList());
        List<SafeLabel> safeLabels = getLabelStructure(companyId);
//            Map<String, List<SafeLabel>> labelRelationMap = getLabelRelationMap(companyId);
        Map<String, List<SafeLabel>> labelRelationMap = getLabelRelationMap(safeLabels);
        labelRouteRelations.forEach(labelRoute -> {
            labelRouteInit(labelRoute, labelRelationMap, companyId);
        });
        return Result.res();
    }


    /**
     * 按公司复制整个标签结构
     *
     * @param fromCompanyId
     * @param toCompanyId
     * @return
     */
    @Transactional
    public boolean copySafeLabel(int fromCompanyId, int toCompanyId) {
        List<SafeLabel> fromLabels = getLabelStructure(fromCompanyId);
        List<SafeLabel> insertLabels = new ArrayList<>();
        fromLabels.forEach(fromLabel -> {
            SafeLabel safeLabel = new SafeLabel();
            safeLabel.setCompanyId(toCompanyId);
            safeLabel.setParent(0);
            safeLabel.setLabel(fromLabel.getLabel());
            constructTableLabels(fromLabel, safeLabel, toCompanyId);
            insertLabels.add(safeLabel);
        });
        insertTableLabels(insertLabels);
        return true;
    }


    private Map<String, List<SafeLabel>> getLabelRelationMap(List<SafeLabel> safeLabelList) {
        Map<String, List<SafeLabel>> map = new HashMap<>();
        if (CollectionUtil.isNotEmpty(safeLabelList))
            safeLabelList.forEach(safeLabel -> {
                List<SafeLabel> safeLabels = new ArrayList<>();
                safeLabels.add(safeLabel);
                getLabelStructRoute(safeLabel, safeLabels, safeLabel.getLabel(), map);
            });
        return map;
    }

    private void getLabelStructRoute(SafeLabel safeLabel, List<SafeLabel> safeLabelList
            , String labelRoute, Map<String, List<SafeLabel>> map) {
        if (CollectionUtil.isNotEmpty(safeLabel.getSafeLabels())) {
            safeLabel.getSafeLabels().forEach(label -> {
                String route = labelRoute + "-" + label.getLabel();
                List<SafeLabel> safeLabels = new ArrayList<>(safeLabelList);
                safeLabels.add(label);
                getLabelStructRoute(label, safeLabels, route, map);
            });
        } else {
            map.put(labelRoute, safeLabelList);
        }
    }

    /**
     * 获取整个标签结构的组合路径
     *
     * @return
     */
    public Map<String, List<SafeLabel>> getLabelRelationMap(int companyId) {
        Map<String, List<SafeLabel>> map = new HashMap<>();
        SafeLabel safeLabel = new SafeLabel();
        safeLabel.setParent(0);
        safeLabel.setCompanyId(companyId);
        List<SafeLabel> safeLabels = safeLabelMapper.search(safeLabel);
        safeLabels.forEach(label -> {
            List<SafeLabel> tempLabels = new ArrayList<>();
            tempLabels.add(label);
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(label.getLabel());
            map.put(label.getLabel(), tempLabels);
            compareLabel(map, stringBuilder.toString(), label, tempLabels);
        });
        return map;
    }

    private void compareLabel(Map<String, List<SafeLabel>> labelRelationMap
            , String labelRoute, SafeLabel safeLabel
            , List<SafeLabel> tempLabels) {
        SafeLabel searchLabel = new SafeLabel();
        searchLabel.setParent(safeLabel.getId());
        List<SafeLabel> subLabels = safeLabelMapper.search(searchLabel);
        if (CollectionUtil.isNotEmpty(subLabels)) {
            subLabels.forEach(label -> {
                List<SafeLabel> labels = new ArrayList<>(tempLabels);
                labels.add(label);
                labelRelationMap.put(labelRoute + "-" + label.getLabel(), labels);
                compareLabel(labelRelationMap, labelRoute + "-" + label.getLabel()
                        , label, labels);
            });
        }
    }

    private void labelRouteInit(String route, Map<String
            , List<SafeLabel>> labelRelationMap
            , int companyId) {
        if (!labelRelationMap.containsKey(route)) {
            //没有该路径的标签组合
            String tempRoute = new String(route);
            if (route.indexOf("-") < 0) {
                SafeLabel safeLabel = new SafeLabel(route);
                safeLabel.setParent(0);
                safeLabel.setCompanyId(companyId);
                safeLabelMapper.insertSelective(safeLabel);
                List<SafeLabel> safeLabels = new ArrayList<>();
                safeLabels.add(safeLabel);
                labelRelationMap.put(route, safeLabels);
            } else {
                labelRouteInit(route.substring(0, route.lastIndexOf("-")), labelRelationMap, companyId);
                List<SafeLabel> safeLabels = new ArrayList<>(labelRelationMap.get(route.substring(0, route.lastIndexOf("-"))));
                SafeLabel label = new SafeLabel(route.substring(route.lastIndexOf("-") + 1, route.length()));
                label.setParent(safeLabels.get(safeLabels.size() - 1).getId());
                label.setCompanyId(companyId);
                safeLabelMapper.insertSelective(label);
                safeLabels.add(label);
                labelRelationMap.put(route, safeLabels);
            }
        }
    }

    /**
     * 构建已经插入过得标签结构
     *
     * @param labels
     * @param parentIdLabelMap
     */
    private void compareSubLabels(List<SafeLabel> labels, Map<Integer, List<SafeLabel>> parentIdLabelMap) {
        labels.forEach(label -> {
            if (parentIdLabelMap.containsKey(label.getId())) {
                List<SafeLabel> safeLabels = parentIdLabelMap.get(label.getId());
                label.setSafeLabels(safeLabels);
                compareSubLabels(label.getSafeLabels(), parentIdLabelMap);
            }else{
                label.setSafeLabels(null);
            }
        });
    }


    /**
     * 构建复制标签的结构，但还未插入,
     * 用于标签复制时，递归创建标签结构
     *
     * @param fromLabel
     * @param toLabel
     * @param companyId
     */
    private void constructTableLabels(SafeLabel fromLabel, SafeLabel toLabel, int companyId) {
        if (CollectionUtil.isNotEmpty(fromLabel.getSafeLabels())) {
            List<SafeLabel> safeLabels = new ArrayList<>();
            fromLabel.getSafeLabels().forEach(label -> {
                SafeLabel safeLabel = new SafeLabel();
                safeLabel.setLabel(label.getLabel());
                safeLabel.setCompanyId(companyId);
                constructTableLabels(label, safeLabel, companyId);
                safeLabels.add(safeLabel);
            });
            toLabel.setSafeLabels(safeLabels);
        }
    }


    /**
     * 按层标签结构层次插入标签
     * —2
     * 1—       —4
     * —3—
     * —5
     * 如上所示，先插入1，再插入2,3，再插入4,5，按层次插入
     */
    private void insertTableLabels(List<SafeLabel> insertLabels) {
        safeLabelMapper.insertList(insertLabels);
        List<SafeLabel> toInsertLabels = new ArrayList<>();
        insertLabels.forEach(label -> {
            if (CollectionUtil.isNotEmpty(label.getSafeLabels())) {
                label.getSafeLabels().forEach(insertLabel -> {
                    insertLabel.setParent(label.getId());
                    toInsertLabels.add(insertLabel);
                });
            }
        });
        if (CollectionUtil.isNotEmpty(toInsertLabels)) {
            insertTableLabels(toInsertLabels);
        }
    }
}
